package com.xherorlclass.discovery.impl;


import com.xherorlclass.Constant;
import com.xherorlclass.ServiceConfig;
import com.xherorlclass.XherorlRpcBootstrap;
import com.xherorlclass.discovery.AbstractRegistry;
import com.xherorlclass.exceptions.DiscoveryException;
import com.xherorlclass.exceptions.NetworkException;
import com.xherorlclass.util.NetUtils;
import com.xherorlclass.util.zookeeper.ZookeeperNode;
import com.xherorlclass.util.zookeeper.ZookeeperUtils;
import com.xherorlclass.watch.UpAndDownWatcher;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooKeeper;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author ：Xherorl
 * @date ：Created in 2023/8/24 10:54
 * @description：
 */
@Slf4j
public class ZookeeperRegistry extends AbstractRegistry {

    // 维护一个zookeeper实例
    private ZooKeeper zooKeeper;

    public ZookeeperRegistry() {
        this.zooKeeper = ZookeeperUtils.createZookeeper();
    }

    public ZookeeperRegistry(String connectionString, int timeOut) {
        this.zooKeeper = ZookeeperUtils.createZookeeper(connectionString, timeOut);
    }

    @Override
    public void register(ServiceConfig<?> service) {
        // 服务名称的节点
        String parentNode = Constant.BASE_PROVIDERS_PATH + "/" + service.getInterface().getName();

        // 这个节点应该是一个持久节点
        if (!ZookeeperUtils.exists(zooKeeper, parentNode, null)){
            ZookeeperNode zookeeperNode = new ZookeeperNode(parentNode, null);
            ZookeeperUtils.createNode(zooKeeper, zookeeperNode, null, CreateMode.PERSISTENT);
        }

        // 创建本机的临时节点， ip:port
        // 服务提供方的端口一般是自己设定，我们还需要一个获取IP的方法
        // IP我们通常是需要一个局域网IP，不是127.0.0.1，也不是IPv6的
        String node = parentNode + "/" + NetUtils.getIp() + ":" + XherorlRpcBootstrap.getInstance().getConfiguration().getPort();
        // 临时节点
        if (!ZookeeperUtils.exists(zooKeeper, node, null)){
            ZookeeperNode zookeeperNode = new ZookeeperNode(node, null);
            ZookeeperUtils.createNode(zooKeeper, zookeeperNode, null, CreateMode.EPHEMERAL);
        }

        if (log.isDebugEnabled()){
            log.debug("服务{}，已经被注册", service.getInterface().getName());
        }
    }

    /**
     * 注册中心的核心目的是什么？拉取合适的服务列表
     * @param serviceName 服务名称
     * @return 服务列表
     */
    @Override
    public List<InetSocketAddress> lookup(String serviceName, String group) {
        // 1、找到服务对应的节点
        String serviceNode = Constant.BASE_PROVIDERS_PATH + "/" + serviceName + "/" + group;
        // 2、从zookeeper中获取它的子节点
        List<String> children = ZookeeperUtils.getChildren(zooKeeper, serviceNode, new UpAndDownWatcher());

        // 获取所有的可用列表
        List<InetSocketAddress> inetSocketAddressList = children.stream().map(ipString -> {
            String[] ipAndPort = ipString.split(":");
            String ip = ipAndPort[0];
            int port = Integer.parseInt(ipAndPort[1]);
            return new InetSocketAddress(ip, port);
        }).collect(Collectors.toList());

        if (inetSocketAddressList.size() == 0){
            throw new DiscoveryException("未发现任何可用的主机");
        }

        return inetSocketAddressList;
    }
}
